package io.noties.markwon.plugin.uml.model

import android.content.Context
import io.noties.markwon.base.R

open class UmlType {
    //type of attributes and parameters, such as int, String, etc.
    //for project types, i.e project classes, it will be extended by UmlClass
    //custom types will be added by user without any class definition
    //type list is at static level
    enum class TypeLevel {
        PRIMITIVE, CUSTOM, PROJECT
    }

    //    **********************************************************************************************
    //    Getters and setters
    //    **********************************************************************************************
    lateinit var name: String
    var typeLevel: TypeLevel
        protected set

    //    **********************************************************************************************
    //    Constructors
    //    **********************************************************************************************
    constructor() {
        typeLevel = TypeLevel.PROJECT
    }

    constructor(name: String, typeLevel: TypeLevel) {
        this.name = name
        this.typeLevel = typeLevel
        umlTypes.add(this)
    }

    fun upgradeToProjectUmlType() {
        //upgrade a class created without type to Project UmlType
        typeLevel = TypeLevel.PROJECT
        umlTypes.add(this)
    }

    //    **********************************************************************************************
    //    Test methods
    //    **********************************************************************************************
    val isPrimitiveUmlType: Boolean
        get() = typeLevel == TypeLevel.PRIMITIVE

    val isCustomUmlType: Boolean
        get() = typeLevel == TypeLevel.CUSTOM
    val isProjectUmlType: Boolean
        get() = typeLevel == TypeLevel.PROJECT

    companion object {
        val umlTypes = ArrayList<UmlType>()
        private const val CUSTOM_TYPES_FILENAME = "custom_types"
        const val JSON_PACKAGE_VERSION_CODE = "PackageVersionCode"
        const val JSON_CUSTOM_TYPES = "CustomTypes"
        fun createUmlType(name: String, typeLevel: TypeLevel) {
            val t = UmlType(name, typeLevel)
        }

        fun valueOf(name: String, inUmlTypes: ArrayList<UmlType>): UmlType? {
            for (t in inUmlTypes) if (t.name == name) return t
            return null
        }

        //    **********************************************************************************************
        //    Modifiers
        //    **********************************************************************************************
        fun clearProjectUmlTypes() {
            for (i in umlTypes.size - 1 downTo 1) if (umlTypes[i].isProjectUmlType
            ) umlTypes.removeAt(i)
        }

        fun clearUmlTypes() {
            umlTypes.clear()
        }

        fun removeUmlType(umlType: UmlType) {
            umlTypes.remove(umlType)
        }

        fun initializePrimitiveUmlTypes(context: Context) {
            val standardTypes = context.resources.getStringArray(R.array.standard_types)
            for (i in standardTypes.indices) createUmlType(standardTypes[i], TypeLevel.PRIMITIVE)
        }

        fun containsPrimitiveUmlTypeNamed(name: String): Boolean {
            for (t in umlTypes) if (t.name == name && t.isPrimitiveUmlType) return true
            return false
        }

        fun containsCustomUmlTypeNamed(name: String): Boolean {
            for (t in umlTypes) if (t.name == name && t.isCustomUmlType) return true
            return false
        }

        fun containsProjectUmlTypeNamed(name: String): Boolean {
            for (t in umlTypes) if (t.name == name && t.isProjectUmlType) return true
            return false
        }

        fun containsUmlTypeNamed(name: String?): Boolean {
            for (t in umlTypes) if (t.name == name) return true
            return false
        }
    }
}
